#include <cstdint>
#include <iostream>
#include <vector>
#include <cassert>
#include <algorithm>
#include <cstring>

#include <ctime>
#include <cstdio>
#include <pthread.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include <unistd.h>
#include <fcntl.h>

#include <functional>
#include <sys/epoll.h>

#include <unordered_map>


//简单的日志打印宏
#define INF 0
#define DBG 1
#define ERR 2
#define LOG_LEVEL INF

// 日志等级转字符串
#define LOG_LEVEL_STR(level) ((level) == INF ? "INF" : ((level) == DBG ? "DBG" : ((level) == ERR ? "ERR" : "UNK")))

#define LOG(level, format, ...) do{\
        if (level < LOG_LEVEL) break;\
        time_t t = time(NULL);\
        struct tm *ltm = localtime(&t);\
        char tmp[32] = {0};\
        strftime(tmp, 31, "%H:%M:%S", ltm);\
        fprintf(stdout, "[%s %p %s %s:%d] " format "\n", LOG_LEVEL_STR(level), (void*)pthread_self(), tmp, __FILE__, __LINE__, ##__VA_ARGS__);\
    }while(0)

#define INF_LOG(format, ...) LOG(INF, format, ##__VA_ARGS__)
#define DBG_LOG(format, ...) LOG(DBG, format, ##__VA_ARGS__)
#define ERR_LOG(format, ...) LOG(ERR, format, ##__VA_ARGS__)


#define BUFFER_DEFAULT_SIZE 1024    //默认缓冲区大小1024字节
class Buffer{
private:
    std::vector<char> _buffer;  //存放缓冲区数据
    uint64_t _reader_index;     //读指针
    uint64_t _writer_index;     //写指针
public:
    Buffer():_buffer(BUFFER_DEFAULT_SIZE),_reader_index(0),_writer_index(0){}

    //缓冲区起始内存地址
    char *begin(){return &_buffer[0];}
    //读指针指向内存地址
    char* readerPos(){return begin() + _reader_index;}
    //写指针指向内存地址
    char* writerPos(){return begin() + _writer_index;}

    //读指针前面空间大小
    uint64_t frontSize(){return readerPos() - begin();}
    //写指针后面空间大小
    uint64_t tailSize(){return _buffer.size() - _writer_index;}
    //缓冲区剩余空间大小
    uint64_t freeSpaceSize(){return tailSize()+frontSize();}
    //可读数据大小
    uint64_t readAbleSize(){return _writer_index - _reader_index;}

    //读指针移动
    void moveReaderIndex(uint64_t len){
        assert(len>=0 && len<=readAbleSize());//先进行安全检查
        _reader_index += len;
    }
    //写指针移动
    void moveWriterIndex(uint64_t len){
        assert(len>=0 && len<=tailSize());//先进行安全检查
        _writer_index += len;
    }
    //写空空间不够时扩容与移动
    void ensureWriteSpace(uint64_t len){
        if(tailSize() >= len){ return; }//1.写指针后空间大于等于写入长度，直接返回
        else if(freeSpaceSize() > len){//2.缓冲区剩余空间大于写入长度，移动数据至开头
            std::copy(readerPos(),writerPos(),begin());
            _writer_index=readAbleSize();
            _reader_index=0;
            std::cout<<"debug:"<<"_writer_index: "<<_writer_index<<" "
                     <<"_reader_index: "<<_reader_index<<std::endl;
        }
        else{//3.缓冲区剩余空间不够时,扩容
            _buffer.resize(len+_writer_index);
        }
    }

    //读操作
    void read(void *buf, uint64_t len) {
        //要求要获取的数据大小必须小于可读数据大小
        assert(len <= readAbleSize());
        std::copy(readerPos(), readerPos() + len, (char*)buf);
        moveReaderIndex(len);
    }

    std::string readAsString(uint64_t len) {//作为string读出数据
        //要求要获取的数据大小必须小于可读数据大小
        assert(len <= readAbleSize());
        std::string str;
        str.resize(len);
        read(&str[0], len);
        return str;
    }

    //读取HTTP一行报文操作
    char *findCRLF() {
        char *res = (char*)memchr(readerPos(), '\n', readAbleSize());
        return res;
    }
    std::string getLine() {
        char *pos = findCRLF();
        if (pos == NULL) {
            return "";
        }
        return readAsString(pos - readerPos() + 1);// +1是为了把换行字符也取出来
    }
    //清空缓冲区
    void clear() {
        //只需要将偏移量归0即可
        _reader_index = 0;
        _writer_index = 0;
    }

    //写操作
    void write(const void *data, uint64_t len){//数据地址+长度写入
        ensureWriteSpace(len);
        const char* d=(const char*)data;
        std::copy(d,d+len,writerPos());
        moveWriterIndex(len);
    }

    void writeString(const std::string &data) {//以string写入
        write(data.c_str(), data.size());
    }

    void writeBuffer(Buffer &data) {//以buffer写入，这就是类似于拷贝构造
        write(data.readerPos(), data.readAbleSize());
    }

};


#define BACKLOG_DEFAULT 1024
class Socket{
private:
    int _sockfd;
public:
    Socket():_sockfd(-1){}
    Socket(int fd):_sockfd(fd){}
    ~Socket(){}
    
    //创建套接字
    bool create(){
        //int socket(int domain, int type, int protocol);
        _sockfd = socket(AF_INET,SOCK_STREAM,0);
        if(_sockfd < 0){
            ERR_LOG("create socket fail!");
            return false;
        }
        return true;
    }

    //绑定套接字
    bool bind(const std::string &ip, uint16_t port){
        //int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen)
        //sockaddr_in 头文件是<netinet/in.h>
        struct sockaddr_in addr;

        //初始化sockaddr_in结构体
        memset(&addr, 0, sizeof(addr));  // 清零结构体
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);  // 主机字节序转网络字节序
        // 使用现代安全的IP转换函数int inet_pton(int af, const char *src, void *dst);
        inet_pton(AF_INET, ip.c_str(), &addr.sin_addr);
        
        //开始绑定
        int ret = ::bind(_sockfd, (struct sockaddr*)&addr, sizeof(sockaddr_in));
        if (ret < 0) {
            ERR_LOG("bind fail: %s:%d", ip.c_str(), port);
            return false;
        }
        return true;
    }

    //监听套接字
    bool listen(int backlog = BACKLOG_DEFAULT)
    {
        //int listen(int sockfd, int backlog);
        int ret =  ::listen(_sockfd, backlog);
        if(ret < 0)
        {
            ERR_LOG("listen fail!");
            return false;
        }
        return true;
    }

    //接收套接字
    int accept()
    {
        //int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
        struct sockaddr_in client_addr;
        socklen_t addr_len = sizeof(struct sockaddr_in);
        
        int newfd = ::accept(_sockfd, (struct sockaddr*)&client_addr, &addr_len);
        if (newfd < 0) {
            ERR_LOG("accept connection failed");
            return -1;
        }
        
        // 获取客户端IP和端口信息
        char client_ip[INET_ADDRSTRLEN];
        inet_ntop(AF_INET,&client_addr.sin_addr,client_ip,INET_ADDRSTRLEN);
        uint16_t client_port = ntohs(client_addr.sin_port);
        INF_LOG("New connection from %s:%d, socket fd: %d", client_ip, client_port, newfd);
        
        return newfd;
    }

    //连接套接字
    bool connect(const std::string& ip,uint16_t port)
    {
        // int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
        sockaddr_in addr;
        memset(&addr, 0, sizeof(addr));
        addr.sin_family=AF_INET;
        addr.sin_port=htons(port);
        inet_pton(AF_INET,ip.c_str(),&addr.sin_addr);

        int ret=::connect(_sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
        if(ret<0)
        {
            ERR_LOG("connect fail:  %s:%d",ip.c_str(),port);
            return false;
        }
        return true;
    }

    //接收数据
    ssize_t recv(void *buf, size_t len, int flag = 0) {
        // ssize_t recv(int sockfd, void *buf, size_t len, int flag);
        ssize_t ret = ::recv(_sockfd, buf, len, flag);
        if (ret <= 0) {
            //EAGAIN 当前socket的接收缓冲区中没有数据了，在非阻塞的情况下才会有这个错误
            //EINTR  表示当前socket的阻塞等待，被信号打断了，
            if (errno == EAGAIN || errno == EINTR) {
                return 0;//表示这次接收没有接收到数据
            }
            ERR_LOG("SOCKET RECV FAILED!!");
            return -1;
        }
        return ret; //实际接收的数据长度
    }

    ssize_t NonBlockRecv(void *buf, size_t len) {
        return recv(buf, len, MSG_DONTWAIT); // MSG_DONTWAIT 表示当前接收为非阻塞。
    }

    //发送数据
    ssize_t send(const void *buf, size_t len, int flag = 0) {
        // ssize_t send(int sockfd, void *data, size_t len, int flag);
        ssize_t ret = ::send(_sockfd, buf, len, flag);
        if (ret < 0) {
            if (errno == EAGAIN || errno == EINTR) {
                return 0;
            }
            ERR_LOG("SOCKET SEND FAILED!!");
            return -1;
        }
            return ret;//实际发送的数据长度
        }

    ssize_t NonBlockSend(void *buf, size_t len) {
        if (len == 0) return 0;
        return send(buf, len, MSG_DONTWAIT); // MSG_DONTWAIT 表示当前发送为非阻塞。
    }
    
    //关闭套接字
    void Close() {
        if (_sockfd != -1) {
            close(_sockfd);
            _sockfd = -1;
        }
    }

    //设置套接字选项---开启地址端口重用
    void ReuseAddress() {
        // int setsockopt(int fd, int leve, int optname, void *val, int vallen)
        int val = 1;
        setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR, (void*)&val, sizeof(int));
        val = 1;
        setsockopt(_sockfd, SOL_SOCKET, SO_REUSEPORT, (void*)&val, sizeof(int));
    }

    //设置套接字阻塞属性-- 设置为非阻塞
    void NonBlock() {
        //int fcntl(int fd, int cmd, ... /* arg */ );
        int flag = fcntl(_sockfd, F_GETFL, 0);
        fcntl(_sockfd, F_SETFL, flag | O_NONBLOCK);
    }   
        
        
    //下面是对上面接口的复用

    //创建一个服务端连接
    bool CreateServer(uint16_t port, const std::string &ip = "0.0.0.0", bool block_flag = false) {
        //1. 创建套接字，2. 绑定地址，3. 开始监听，4. 设置非阻塞， 5. 启动地址重用
        if (create() == false) return false;
        if (block_flag) NonBlock();
        if (bind(ip, port) == false) return false;
        if (listen() == false) return false;
        ReuseAddress();
        return true;
    }

    //创建一个客户端连接
    bool CreateClient(uint16_t port, const std::string &ip) {
        //1. 创建套接字，2.指向连接服务器
        if (create() == false) return false;
        if (connect(ip, port) == false) return false;
        return true;
    }

};


class Poller;
class Channel {
    private:
        Poller* _poller;
        int _fd;
        uint32_t _events;  // 当前需要监控的事件
        uint32_t _revents; // 当前连接触发的事件
        using EventCallback = std::function<void()>;
        EventCallback _read_callback;   //可读事件被触发的回调函数
        EventCallback _write_callback;  //可写事件被触发的回调函数
        EventCallback _error_callback;  //错误事件被触发的回调函数
        EventCallback _close_callback;  //连接断开事件被触发的回调函数
        EventCallback _event_callback;  //任意事件被触发的回调函数
    public:
        Channel(Poller * poller ,int fd):_poller(poller), _fd(fd),_events(0),_revents(0){}
        int Fd() { return _fd; }
        void SetREvents(uint32_t events) { _revents = events; }//设置实际就绪的事件
        uint32_t Events() { return _events; }//获取想要监控的事件
        void SetReadCallback(const EventCallback &cb) { _read_callback = cb; }
        void SetWriteCallback(const EventCallback &cb) { _write_callback = cb; }
        void SetErrorCallback(const EventCallback &cb) { _error_callback = cb; }
        void SetCloseCallback(const EventCallback &cb) { _close_callback = cb; }
        void SetEventCallback(const EventCallback &cb) { _event_callback = cb; }
        //当前是否监控了可读
        bool ReadAble() { return (_events & EPOLLIN); } 
        //当前是否监控了可写
        bool WriteAble() { return (_events & EPOLLOUT); }
        //启动读事件监控
        void EnableRead() { _events |= EPOLLIN; Update();}
        //启动写事件监控
        void EnableWrite() { _events |= EPOLLOUT; Update();}
        //关闭读事件监控
        void DisableRead() { _events &= ~EPOLLIN; Update();}
        //关闭写事件监控
        void DisableWrite() { _events &= ~EPOLLOUT; Update();}
        //关闭所有事件监控
        void DisableAll() { _events = 0; Update();}
        // //移除监控
        // void Remove(){/*调用EventLoop接口来解除事件监控*/}

        void Remove();  // 声明
        void Update();  // 声明


        //事件处理，一旦连接触发了事件，就调用这个函数，自己触发了什么事件如何处理自己决定
        void HandleEvent() {
            if ((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI)) {
                if (_event_callback) _event_callback();/*不管任何事件，都调用的回调函数*/
                if (_read_callback) _read_callback();
            }

            /*有可能会释放连接的操作事件，一次只处理一个*/
            if (_revents & EPOLLOUT) {
                if (_write_callback) _write_callback();
                if (_event_callback) _event_callback();/*不管任何事件，都调用的回调函数*/
            }else if (_revents & EPOLLERR) {
                if (_event_callback) _event_callback();/*不管任何事件，都调用的回调函数*/
                if (_error_callback) _error_callback();//一旦出错，就会释放连接，因此要放到前边调用
            }else if (_revents & EPOLLHUP) {
                if (_event_callback) _event_callback();/*不管任何事件，都调用的回调函数*/
                if (_close_callback) _close_callback();//一旦出错，就会释放连接，因此要放到前边调用
            }
        }
};


#define MAX_EPOLLEVENTS 1024
class Poller {
    private:
        int _epfd;
        struct epoll_event _evs[MAX_EPOLLEVENTS];
        std::unordered_map<int, Channel *> _channels;
    private:
        //对epoll的直接操作
        void Update(Channel *channel, int op) {
            // int epoll_ctl(int epfd, int op,  int fd,  struct epoll_event *ev);
            int fd = channel->Fd();
            struct epoll_event ev;
            ev.data.fd = fd;
            ev.events = channel->Events();
            int ret = epoll_ctl(_epfd, op, fd, &ev);
            if (ret < 0) {
                ERR_LOG("EPOLLCTL FAILED!");
            }
            return;
        }
        //判断一个Channel是否已经添加了事件监控
        bool HasChannel(Channel *channel) {
            auto it = _channels.find(channel->Fd());
            if (it == _channels.end()) {
                return false;
            }
            return true;
        }
    public:
        Poller() {
            _epfd = epoll_create(MAX_EPOLLEVENTS);
            if (_epfd < 0) {
                ERR_LOG("EPOLL CREATE FAILED!!");
                abort();//退出程序
            }
        }
        //添加或修改监控事件
        void UpdateEvent(Channel *channel) {
            bool ret = HasChannel(channel);
            if (ret == false) {
                //不存在则添加
                _channels.insert(std::make_pair(channel->Fd(), channel));
                return Update(channel, EPOLL_CTL_ADD);
            }
            return Update(channel, EPOLL_CTL_MOD);
        }
        //移除监控
        void RemoveEvent(Channel *channel) {
            auto it = _channels.find(channel->Fd());
            if (it != _channels.end()) {
                _channels.erase(it);
            }
            Update(channel, EPOLL_CTL_DEL);
        }
        //开始监控，返回活跃连接
        void Poll(std::vector<Channel*> *active) {
            // int epoll_wait(int epfd, struct epoll_event *evs, int maxevents, int timeout)
            int nfds = epoll_wait(_epfd, _evs, MAX_EPOLLEVENTS, -1);
            if (nfds < 0) {
                if (errno == EINTR) {
                    return ;
                }
                ERR_LOG("EPOLL WAIT ERROR:%s\n", strerror(errno));
                abort();//退出程序
            }
            for (int i = 0; i < nfds; i++) {
                auto it = _channels.find(_evs[i].data.fd);
                assert(it != _channels.end());
                it->second->SetREvents(_evs[i].events);//设置实际就绪的事件
                active->push_back(it->second);
            }
            return;
        }
};

// Channel类方法的实现（在Poller类定义之后）
inline void Channel::Remove() {
    _poller->RemoveEvent(this);
}

inline void Channel::Update() {
    _poller->UpdateEvent(this);
}
